/**

This file is part of MaCI/GIMnet.

MaCI/GIMnet is free software: you can redistribute it and/or modify it 
under the terms of the GNU Lesser General Public License as published 
by the Free Software Foundation, either version 3 of the License, or 
(at your option) any later version.

MaCI/GIMnet is distributed in the hope that it will be useful, but WITHOUT 
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
License for more details.

You should have received a copy of the GNU Lesser General Public 
License along with GIMnet. (See COPYING.LESSER) If not, see 
<http://www.gnu.org/licenses/>.

**/
/*Title: mjbWorld
   Copyright (c) 1998-2002 Martin John Baker

This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General License
   as published by the Free Software Foundation; either version 2
   of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
   GNU General License for more details.

For information about the GNU General License see http://www.gnu.org/

To discuss this program http://sourceforge.net/forum/forum.php?forum_id=122133
   also see website http://www.euclideanspace.com/
   */

/*
   for theory see:
   http://www.euclideanspace.com/maths/vectors/index.htm
   */

//#include "mjbModel.h"
#include "sfvec3f.h"
#include <math.h>
   /* x3d definition

<!ENTITY % SFVec3f "CDATA"> <!-- ArrayList3Float -->
   */

   //private sfvec3fEditor editor = null;

 // VRML only supports float but allow override if higher resolution required

sfvec3f::sfvec3f(double x1,double y1,double z1) {
   x=x1;
   y=y1;
   z=z1;
   
   }

sfvec3f::sfvec3f(sfvec3f* in) { // copy constructor
   x=(in) ? in->x : 0;
   y= (in) ? in->y : 0;
   z= (in) ? in->z : 1;
  
   }

sfvec3f::sfvec3f() {
  
   }


/*
   for theory see:
   http://www.euclideanspace.com/maths/vectors/index.htm
   */
   void sfvec3f::sub(sfvec3f* other){
   x-= other->x;
   y-= other->y;
   z-= other->z;
   }

/*
   for theory see:
   http://www.euclideanspace.com/maths/vectors/index.htm
   */
   void sfvec3f::add(sfvec3f* other){
   x+= other->x;
   y+= other->y;
   z+= other->z;
   }

/*
   for theory see:
   http://www.euclideanspace.com/maths/vectors/normals/index.htm
   */
   void sfvec3f::normalize(){
   double t = sqrt(x*x + y*y + z*z);
   x /= t;
   y /= t;
   z /= t;
   }

void sfvec3f::scale(double sc){
   x *= sc;
   y *= sc;
   z *= sc;
   }
   
   double sfvec3f::distanceSquared(sfvec3f* other){
   double x1 = other->x - x;
   double y1 = other->y - y;
   double z1 = other->z - z;
   return x1*x1 + y1*y1 + z1*z1;
   }

void sfvec3f::cross(sfvec3f* other) {
   double xh = y * other->z - other->y * z;
   double yh = z * other->x - other->z * x;
   double zh = x * other->y - other->x * y;
   x = xh;
   y = yh;
   z = zh;
   }

double sfvec3f::dot(sfvec3f* other) {
   return (x * other->x) + (y * other->y) + (z * other->z);
   }


void sfvec3f::setX(double v) {
   x=v;
   }

void sfvec3f::setY(double v) {
   y=v;
   }

void sfvec3f::setZ(double v) {
   z=v;
   }

double sfvec3f::getx() {
   return x;
   }

double sfvec3f::gety() {
   return y;
   }

double sfvec3f::getz() {
   return z;
   }

sfvec3f* sfvec3f::minus() {
   return new sfvec3f(-x,-y,-z);
   }



bool sfvec3f::greaterThan(sfvec3f* other) {
   if (other->x > x) return true;
   if (other->y > y) return true;
   if (other->z > z) return true;
   return false;
   }

bool sfvec3f::lessThan(sfvec3f* other) {
   if (other->x < x) return true;
   if (other->y < y) return true;
   if (other->z < z) return true;
   return false;
   }

bool sfvec3f::Equals(sfvec3f* v2) {
   if (!v2) return false;
   if (x!= v2->x) return false;
   if (y!= v2->y) return false;
   if (z!= v2->z) return false;
   return true;
   }

/** use to combine bounds
   * if i=0 take minimum otherwise maximum */
   void sfvec3f::combine(sfvec3f* other,int i){
   if (i==0) { // take minimum
   if (other->x < x) x=other->x;
   if (other->y < y) y=other->y;
   if (other->z < z) z=other->z;
   } else { // take maximum
   if (other->x > x) x=other->x;
   if (other->y > y) y=other->y;
   if (other->z > z) z=other->z;
   }
   }


